


//
//  JCPropertyDescription.m
//  JCSDK
//
//  Created by master on 16/2/24.
//  Copyright © 2016年 AdMaster. All rights reserved.
//

#import "JCPropertyDescription.h"

@interface JCPropertyDescription ()

@property (nonatomic, readonly,copy) NSPredicate *predicate;

@end
@implementation JCPropertyDescription

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    NSParameterAssert(dictionary[@"name"] != nil);
    
    if(self = [super init]) {
        _name = dictionary[@"name"];
        _useInstanceVariableAccess = [dictionary[@"use_ivar"] boolValue];
        _readOnly = [dictionary[@"readonly"] boolValue];
        _nofollow = [dictionary[@"nofollow"] boolValue];
        
        NSString *predicateFormate = dictionary[@"predicate"];
        
        if(predicateFormate) {
            _predicate = [NSPredicate predicateWithFormat:predicateFormate];
        }
        
        //get method if nil
        NSDictionary *getDictionary = dictionary[@"get"];
        if(getDictionary == nil) {
            NSParameterAssert(dictionary[@"type"] != nil);
            getDictionary = @{
                    @"selector" : _name,
                    @"result" : @{
                            @"type" : dictionary[@"type"],
                            @"name" : @"value"
                            },
                    @"parameters": @[]
                    };
        }
        // set method if nil
        NSDictionary *setDictionary = dictionary[@"set"];
        if(setDictionary == nil && _readOnly == NO) {
            setDictionary = @{
                    @"selector" : [NSString stringWithFormat:@"set%@:", [_name capitalizedString]],
                    @"parameters" : @[
                            @{
                                @"name" : @"value",
                                @"type" : dictionary[@"type"]
                                }
                            ]
                    };
        }
        
        
        
        _getSelectorDescription = [[JCSelectorDescription alloc] initWithDictionary:getDictionary];
        if(setDictionary) {
            _setSelectorDescription = [[JCSelectorDescription alloc] initWithDictionary:setDictionary];
        } else {
            _readOnly = YES;
        }
        
        BOOL useKVC = (dictionary[@"use_kvc"] == nil ? YES :[dictionary[@"use_kvc"] boolValue])
                       &&
                      _useInstanceVariableAccess == NO;
        
        //TODO: setter method parameter count == 1
        _useKVC = useKVC  &&
                  [_getSelectorDescription.parameters count] == 0 &&
        (_setSelectorDescription == nil || _setSelectorDescription.parameters.count == 1);

    }
    return self;
}

//返回值type 通过selector 返回值返回
- (NSString *)type
{
    return _getSelectorDescription.returnType;
}

- (BOOL)shouldReadPropertyValueForObject:(NSObject *)object {
    if(_nofollow) return NO;
    if (_predicate) {
        return [_predicate evaluateWithObject:object];
    }
    return YES;
}

- (NSValueTransformer *)valueTransformer
{
    return [[self class] valueTransformerForType:self.type];
}

+ (NSValueTransformer *)valueTransformerForType:(NSString *)typeName
{
    // TODO: lookup transformer by type
    
    for (NSString *toTypeName in @[@"NSDictionary", @"NSNumber", @"NSString"]) {
        NSString *toTransformerName = [NSString stringWithFormat:@"JC%@To%@ValueTransformer", typeName, toTypeName];
        NSValueTransformer *toTransformer = [NSValueTransformer valueTransformerForName:toTransformerName];
        if (toTransformer) {
            return toTransformer;
        }
    }
    
    // Default to pass-through.
    return [NSValueTransformer valueTransformerForName:@"JCPassThroughValueTransformer"];
}
@end

@implementation JCSelectorDescription

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
     NSString *k_selector = @"selector";
    NSString *k_parameters = @"parameters";
    NSString *k_result = @"result";
    
    NSParameterAssert(dictionary[k_selector] != nil);
    NSParameterAssert(dictionary[k_parameters] != nil);
    
    if(self = [super init]) {
        _selector = dictionary[k_selector];
        NSMutableArray *parameters = [NSMutableArray arrayWithCapacity:[dictionary[k_parameters] count]];
        for (NSDictionary *parameterDictionary in dictionary[k_parameters]) {
            JCSelectorParameters *parameter = [[JCSelectorParameters alloc] initWithDictionary:parameterDictionary];
            [parameters addObject:parameter];
        }
        _parameters = parameters;
        _returnType = dictionary[k_result][@"type"]; //optional
    }
    return self;
}


@end

@implementation JCSelectorParameters

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    NSParameterAssert(dictionary[@"type"] != nil);
    NSParameterAssert(dictionary[@"name"] != nil);
    
    if(self = [super init]) {
        _name = dictionary[@"name"];
        _type = dictionary[@"type"];
    }
    
    return self;
}


@end
